package com.ruoyi.ability

import cn.hutool.http.HttpUtil
import cn.hutool.json.JSONUtil
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.ruoyi.back.domain.v3.StyleSetting
import com.ruoyi.back.service.FunctionService
import com.ruoyi.back.service.v3.SensitiveWordRecordDto
import com.ruoyi.back.service.v3.SensitiveWordRecordService
import com.ruoyi.back.service.v3.SensitiveWordService
import com.ruoyi.back.service.v3.StyleSettingService
import com.ruoyi.config.*
import com.ruoyi.exception.FlyException
import com.tencentcloudapi.aiart.v20221229.models.ImageToImageRequest
import com.tencentcloudapi.aiart.v20221229.models.ImageToImageResponse
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import okhttp3.MediaType
import okhttp3.Request
import okhttp3.RequestBody
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.stereotype.Service
import java.time.format.TextStyle


@Service
@EnableConfigurationProperties(TencentApiProperties::class, BaiduApiProperties::class)
class Ability {

    @Autowired
    private lateinit var tencentApiProperties: TencentApiProperties

    @Autowired
    private lateinit var baiduApiProperties: BaiduApiProperties

    @Autowired
    private lateinit var functionService: FunctionService

    @Autowired
    private lateinit var styleSettingService: StyleSettingService


    fun initStyle() {

        val textStyle = listOf(
            "探索无限",
            "古风",
            "二次元",
            "写实风格",
            "浮世绘",
            "low poly",
            "未来主义",
            "像素风格",
            "概念艺术",
            "赛博朋克",
            "洛丽塔风格",
            "巴洛克风格",
            "超现实主义",
            "水彩画",
            "蒸汽波艺术",
            "油画",
            "卡通画"
        )

        val data = mutableListOf<StyleSetting>()
        data.addAll(textStyle.map {
            StyleSetting().apply {
                type = 1
                name = it
            }
        })

        data.addAll(listOf(
            StyleSetting().apply {
                type = 2
                name = "水彩画"
                num = "106"
            },
            StyleSetting().apply {
                type = 2
                name = "日系动漫"
                num = "201"
            },
            StyleSetting().apply {
                type = 2
                name = "美系动漫"
                num = "202"
            },
            StyleSetting().apply {
                type = 2
                name = "唯美古风"
                num = "203"
            },
            StyleSetting().apply {
                type = 2
                name = "不限定风格"
                num = "000"
            }
        ))

        data.addAll(

            listOf(
                StyleSetting().apply {
                    type = 3
                    name = "迪士尼真人头像"
                    param = "0"
                },
                StyleSetting().apply {
                    type = 3
                    name = "3D迪士尼头像"
                    param = "1"
                },
                StyleSetting().apply {
                    type = 3
                    name = "芭比"
                    param = "2"
                },
                StyleSetting().apply {
                    type = 3
                    name = "日系卡通"
                    param = "3"
                },
                StyleSetting().apply {
                    type = 3
                    name = "言情风格头像"
                    param = "4"
                },
                StyleSetting().apply {
                    type = 3
                    name = "言情风格全身/多人"
                    param = "5"
                },
                StyleSetting().apply {
                    type = 3
                    name = "像素化"
                    param = "6"
                },
                StyleSetting().apply {
                    type = 3
                    name = "笑脸卡通"
                    param = "7"
                },
                StyleSetting().apply {
                    type = 3
                    name = "迪士尼真人/多人"
                    param = "8"
                },
                StyleSetting().apply {
                    type = 3
                    name = "美漫头像"
                    param = "9"
                },
                StyleSetting().apply {
                    type = 3
                    name = "美漫全身"
                    param = "10"
                },
                StyleSetting().apply {
                    type = 3
                    name = "新版皮克斯头像"
                    param = "11_header"
                },
                StyleSetting().apply {
                    type = 3
                    name = "新版皮克斯全身"
                    param = "11_full"
                },
                StyleSetting().apply {
                    type = 3
                    name = "粉扑扑头像"
                    param = "12_header"
                },
                StyleSetting().apply {
                    type = 3
                    name = "粉扑扑全身"
                    param = "12_full"
                }
            )
        )
        data.forEach {
            styleSettingService.save(it)
        }
    }

    fun textTopic(textToPicParam: TextToPicParam): String {

        val mediaType: MediaType? = MediaType.parse("application/json")
        textToPicParam.resolution = functionService.getById(textToPicParam.functionId)?.name
        val body: RequestBody = RequestBody.create(mediaType, JSONUtil.toJsonStr(textToPicParam))
        val request: Request = Request.Builder()
            .url("https://aip.baidubce.com/rpc/2.0/ernievilg/v1/txt2img?access_token=" + baiduApiProperties.token())
            .method("POST", body)
            .addHeader("Content-Type", "application/json")
            .addHeader("Accept", "application/json")
            .build()
        val response = HTTP_CLIENT.newCall(request).execute()
        return response.body()?.string() ?: throw FlyException("网络错误")
    }

    fun text2PicResult(taskId: String): String {

        val mediaType = MediaType.parse("application/json")
        val body = RequestBody.create(mediaType, JSONUtil.toJsonStr(mapOf("taskId" to taskId)))
        val request = Request.Builder()
            .url("https://aip.baidubce.com/rpc/2.0/ernievilg/v1/getImg?access_token=" + baiduApiProperties.token())
            .method("POST", body)
            .addHeader("Content-Type", "application/json")
            .addHeader("Accept", "application/json")
            .build()
        val response = HTTP_CLIENT.newCall(request).execute()
        return response.body()?.string() ?: throw FlyException("网络错误")
    }


    fun picToPic(picParam: PicToPicParam): String =
        tencentApiProperties.client().let { client ->
            ImageToImageResponse.toJsonString(client.ImageToImage(ImageToImageRequest().apply {
                inputUrl = picParam.inputUrl
                prompt = picParam.prompt
                negativePrompt = picParam.negativePrompt
                styles = styleSettingService.list(KtQueryWrapper(StyleSetting::class.java)
                    .`in`(StyleSetting::id, picParam.styles?.split(",")))
                    .takeIf { it.isNotEmpty() }
                    ?.run { map { it.num }.toTypedArray() }
                resultConfig = com.tencentcloudapi.aiart.v20221229.models.ResultConfig().apply {
                    resolution = functionService.getById(picParam.functionId)?.name
                }
                logoAdd = 0
                strength = picParam.strength
            }))
        }


    fun cartoonPic(cartoonParam: CartoonParam): String =
        HttpUtil.createGet("https://picupapi.tukeli.net/api/v1/cartoonSelfieByUrl")
            .addHeaders(mapOf("APIKEY" to "ed9c16db6d304eeeabfaa09855accbf4"))
            .form(
                mapOf(
                    "cartoonType" to styleSettingService.getById(cartoonParam.style)?.param,
                    "url" to cartoonParam.inputUrl!!,
                    "outputFormat" to "png"
                )
            )
            .execute()
            .body()
            .let { result ->
                JSONUtil.parseObj(result)
                    .let { jsonObject ->
                        jsonObject.getInt("code")
                            .takeIf { it != 0 }
                            ?.run { throw FlyException(jsonObject.getStr("msg")) }
                            ?: run {
                                result
                            }
                    }

            }
}




@ApiModel("文生图参数")
data class TextToPicParam(

    @ApiModelProperty("用户id")
    var userId: Long? = null,

    @ApiModelProperty("渠道号")
    var channelCode: String? = null,

    @ApiModelProperty("是否是支付后的创作")
    var pay: Boolean? = false,

    @ApiModelProperty("输入内容，长度不超过100个字")
    var text: String? = null,

    var resolution: String? = null,

    @ApiModelProperty("功能尺寸id")
    var functionId: Long? = null,

    @ApiModelProperty("风格id")
    var style: String? = null,

    @ApiModelProperty("图片生成数量，支持1-6张")
    var num: Int? = 1
)


@ApiModel("头像开通化参数")
data class CartoonParam(

    @ApiModelProperty("用户id")
    var userId: Long? = null,

    @ApiModelProperty("渠道号")
    var channelCode: String? = null,

    @ApiModelProperty("是否是支付后的创作")
    var pay: Boolean? = false,

    @ApiModelProperty("风格id")
    var style: String? = null,

    @ApiModelProperty("原始图片")
    var inputUrl: String? = null
)


@ApiModel("图生图参数")
data class PicToPicParam(

    @ApiModelProperty("用户id")
    var userId: Long? = null,

    @ApiModelProperty("渠道号")
    var channelCode: String? = null,

    @ApiModelProperty("是否是支付后的创作")
    var pay: Boolean? = false,

    @ApiModelProperty("原始图片")
    var inputUrl: String? = null,

    @ApiModelProperty("描述词")
    var prompt: String? = null,

    @ApiModelProperty("不希望出现的内容")
    var negativePrompt: String? = null,

    @ApiModelProperty("多个风格使用逗号拼接")
    var styles: String? = null,

    @ApiModelProperty("功能尺寸id")
    var functionId: Long? = null,

    //@ApiModelProperty("直接传尺寸")
    //var resultConfig: String? = null,

    @ApiModelProperty("原图参考度")
    var strength: Float? = null,
)
